package com.dsunsoft.rtu.web;

import com.dsunsoft.rtu.common.constant.CommonConstants;
import com.dsunsoft.rtu.common.constant.RtuCommandConstants;
import com.dsunsoft.rtu.common.entity.RestCode;
import com.dsunsoft.rtu.common.entity.RestResult;
import com.dsunsoft.rtu.common.exception.BizException;
import com.dsunsoft.rtu.common.util.CommonUtils;
import com.dsunsoft.rtu.entity.OnlineDevice;
import com.dsunsoft.rtu.entity.SocketRequest;
import com.dsunsoft.rtu.netty.NettyChannelMap;
import io.netty.channel.Channel;
import io.netty.channel.socket.SocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * socket
 */
@Slf4j
@RestController
@RequestMapping("/api/socket")
public class SocketController {


    /**
     * 发送消息【外部调用】
     */
    @PostMapping(value = "/send")
    public RestResult<String> send(@RequestBody SocketRequest socketRequest) throws BizException {
        if (socketRequest.getDeviceId() == null || StringUtils.isBlank(socketRequest.getBizType())) {
            return new RestResult<String>().failure("设备ID或业务类型不能为空");
        }
        Channel channel = NettyChannelMap.get(socketRequest.getDeviceId());
        if (channel == null) {
            return new RestResult<String>().failure("设备不在线,无法发送消息");
        }
        if (!channel.isActive()) {
            return new RestResult<String>().failure("设备不在线,无法发送消息");
        }
        // 根据请求业务类型获取指令
        String command = getRequestBizTypeCommand(socketRequest);
        log.info("send: [" + socketRequest + "], msg: " + command);
        // 发送指令
        byte[] resMsg = CommonUtils.hexToBytes(command);
        channel.writeAndFlush(resMsg);
        return new RestResult<>(RestCode.SUCCESS, command);
    }

    /**
     * 发送消息【系统调用】
     */
    @PostMapping(value = "/sendByRtu")
    public RestResult<String> sendByRtu(@RequestBody SocketRequest socketRequest) throws BizException {
        if (socketRequest.getDeviceId() == null || StringUtils.isBlank(socketRequest.getBizType())) {
            return new RestResult<String>().failure("设备ID或业务类型不能为空");
        }
        Channel channel = NettyChannelMap.get(socketRequest.getDeviceId());
        if (channel == null) {
            return new RestResult<String>().failure("设备不在线,无法发送消息");
        }
        if (!channel.isActive()) {
            return new RestResult<String>().failure("设备不在线,无法发送消息");
        }
        // 根据请求业务类型获取指令
        String command = getRequestBizTypeCommand(socketRequest);
        log.info("send: [" + socketRequest + "], msg: " + command);
        // 发送指令
        byte[] resMsg = CommonUtils.hexToBytes(command);
        channel.writeAndFlush(resMsg);
        return new RestResult<>(RestCode.SUCCESS, command);
    }

    /**
     * 根据请求业务类型获取指令
     *
     * @param socketRequest socketRequest
     * @return 指令
     */
    private String getRequestBizTypeCommand(SocketRequest socketRequest) throws BizException {
        // rtu指令
        String command;
        // 设备ID转16进制
        String hexDeviceId = CommonUtils.intToHexString(socketRequest.getDeviceId());
        switch (socketRequest.getBizType()) {
            case CommonConstants.BIZ_TYPE_CALL_CAMERA:
                // 召测摄像机
                command = MessageFormat.format(RtuCommandConstants.CALL_CAMERA, hexDeviceId);
                break;
            case CommonConstants.BIZ_TYPE_OPEN_CAMERA:
                // 断电
                command = MessageFormat.format(RtuCommandConstants.OPEN_CAMERA, hexDeviceId);
                break;
            case CommonConstants.BIZ_TYPE_CLOSE_CAMERA:
                // 上电
                command = MessageFormat.format(RtuCommandConstants.CLOSE_CAMERA, hexDeviceId);
                break;
            case CommonConstants.BIZ_TYPE_SET_CALL_CAMERA_MINUTE:
                // 设置摄像机召测时间,单位分钟
                if (socketRequest.getMinute() == null) {
                    throw new BizException("召测摄像机分钟不能为空");
                }
                command = MessageFormat.format(RtuCommandConstants.SET_CALL_CAMERA_MINUTE, hexDeviceId, CommonUtils.intToHexString(socketRequest.getMinute()));
                break;
            case CommonConstants.BIZ_TYPE_SET_CAMERA_POWER_MINUTE:
                // 设置摄像机供电时间,单位分钟
                if (socketRequest.getMinute() == null) {
                    throw new BizException("设置摄像机分钟不能为空");
                }
                command = MessageFormat.format(RtuCommandConstants.SET_CAMERA_POWER_MINUTE, hexDeviceId, CommonUtils.intToHexString(socketRequest.getMinute()));
                break;
            case CommonConstants.BIZ_TYPE_SET_RTU_TIME:
                // 设置RTU仪器为服务器当前时间
                command = MessageFormat.format(RtuCommandConstants.SET_RTU_TIME, hexDeviceId, CommonUtils.getCurrentTimeOfRTU());
                break;
            case CommonConstants.BIZ_TYPE_CUSTOM_COMMAND:
                // 自定义命令
                if (StringUtils.isBlank(socketRequest.getCustomCommand())) {
                    throw new BizException("自定义命令不能为空");
                }
                command = socketRequest.getCustomCommand();
                break;
            default:
                throw new BizException("业务类型错误");
        }
        return command;
    }
}
